//
// Created by F1997 on 2024/10/17.
//

#ifndef NETWORK_TRAFFIC_PROCESSING_PCH_H
#define NETWORK_TRAFFIC_PROCESSING_PCH_H

// 预编译头文件，可以防止头文件重复导入，且统一管理不同平台特有的头文件
// ===================================================================== 头文件
// TODO:使用的内库
// c 的

// c++ 的
#include <string>
#include <chrono>
#include <iostream>
#include <sstream>
#include <time.h>
#include <iomanip> // 科学计数法转换，注意包含这个头文件
#include <fstream>
#include <filesystem>
#include <cstring>
#include <regex>
#include <algorithm>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <map>
#include <unordered_map>
#include <stdio.h>
#include <csignal>
#include <functional> // 包含std::function的头文件，用于在main后执行逻辑


#ifdef _WIN32
// windows 特有的内库
#include <windows.h>
#include <direct.h>
#else
// linux 特有的内库
#include <unistd.h> // linux下加入的应用
#include <iconv.h>
#include <future>
#include <thread>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <sys/wait.h>
//#include <bits/mqueue.h> // 需要添加动态库
#include <future>
//#include <atomic> // 原子操作
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <numeric>

#include <queue>

#endif

// TODO:特定项目使用的第三方库
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include <spdlog/sinks/rotating_file_sink.h>
#include "spdlog/async.h"

#include "pcap.h"

#include "tins/tins.h"

// TODO: 项目内共有的
#include "../main/main.h"

// ===================================================================== 多个源文件共享的结构体
// ===================================================================== 统计用的结构体 ↓↓↓↓↓↓
namespace Global {
    extern int g_exit; // 退出标志

    // 声明全局变量
    extern std::string globalString; // 声明而非定义
    extern int globalInt;
}

// 共享的结构体
struct MarketData {
    // 行情无关
    std::string lineFlag; // 线路标记

    int len; // 报文长度
    long long caplen; // 实际捕获的数据包长度
    std::chrono::high_resolution_clock::time_point local_time; // 本地接收时间，应用程序本地时间
    uint64_t avg_local_time; // 本地平均时间
    time_t time1; // 抓包时间，秒
    time_t time2; // 抓包时间，纳秒
    int pkgCount; // 当前包数量，包的自定义编号，从1开始
    int statistic_num; // 写入队列的次数
    std::string destinationIP;

    // 行情相关-解码前
    struct pcap_pkthdr* pkthdr;
    const u_char* packet; // 原始数据报
    // 解码后
    int packet_no; // 行情包的唯一编号
    uint32_t snap_time;
    uint16_t snap_millisec;
    std::string inst_name; // 合约名称
    double price;
    double volume;
};

// 统计的指标结构体
struct SaveDataStruct {
    // 行情无关
    long long staticCount; // 统计次数
    std::string fastFlag; // 快的一路标记
    std::chrono::high_resolution_clock::time_point local_time1; // 本地时间
    std::chrono::high_resolution_clock::time_point local_time2; // 本地时间
    long long pkgCount1; // 当前收到的总包数
    long long pkgCount2; // 当前收到的总包数
    long long lineCount1; // line1先到的包数
    long long lineCount2; // line1先到的包数
    long long avgDiff; // 平均延迟差

    long long maxDiff; // 最大延迟差
    long long minDiff; // 最小延迟差
};

// ===================================================================== 统计用的结构体 ↑↑↑↑↑↑

// ===================================================================== 基础报文结构体 ↓↓↓↓↓↓
#pragma pack(1)
// 小端序、1字节对齐
// 结构体是由pcap_loop自己填充的，用来取得一些关于数据包的信息
struct my_pcap_pkthdr {
    struct timeval ts;   /* 时间戳 */
    bpf_u_int32 caplen;   /* 已捕获部分的长度 */
    bpf_u_int32 len;  /* 该包的脱机长度 */
};

// 定义以太网头部结构，14字节
struct my_ether_header {
    u_int8_t ether_dhost[6]; // 目的MAC地址
    u_int8_t ether_shost[6]; // 源MAC地址
    u_int16_t ether_type;    // 协议类型
};

// 定义IP头部结构，20字节
struct my_ip_header {
    u_int8_t ip_hl : 4, ip_v : 4; // IP头部长度和版本
    u_int8_t ip_tos;              // 服务类型
    u_int16_t ip_len;             // 总长度
    u_int16_t ip_id;              // 标识
    u_int16_t ip_off;             // 标志和段偏移
    u_int8_t ip_ttl;              // 生存时间
    u_int8_t ip_p;                // 协议
    u_int16_t ip_sum;             // 校验和
    struct in_addr ip_src;        // 源IP地址
    struct in_addr ip_dst;        // 目的IP地址
};

// 定义TCP头部结构，20字节
struct my_tcp_header {
    u_int16_t th_sport;           // 源端口
    u_int16_t th_dport;           // 目的端口
    u_int32_t th_seq;             // 序列号
    u_int32_t th_ack;             // 确认号
    u_int8_t th_off : 4, th_x2 : 4; // 数据偏移和保留位
    u_int8_t th_flags;            // 标志
    u_int16_t th_win;             // 窗口大小
    u_int16_t th_sum;             // 校验和
    u_int16_t th_urp;             // 紧急指针
};

// 定义UDP头部结构，8字节
struct my_udp_header {
    uint16_t SrcPort;    // 源端口号
    uint16_t DstPort;    // 目的端口号
    uint16_t len;        // 数据包长度
    uint16_t checkSum;   // 校验和
};

struct my_udp_header2 {
    u_int16_t SrcPort;    // 源端口号 ，u_int16_t和uint16_t的区别主要体现在定义来源和标准化程度上
    u_int16_t DstPort;    // 目的端口号
    uint16_t len;        // 数据包长度
    uint16_t checkSum;   // 校验和
};

#pragma pack()
// ===================================================================== 基础报文结构体 ↑↑↑↑↑↑

// ===================================================================== 数据类型重命名 ↓↓↓↓↓↓

// TODO:跨平台数据类型
#ifdef _WIN32
// windows 特有的
#define PATH_CHAR_T wchar_t
#define PATH_TEXT(x) L##x
#else
// linux 特有的
#define PATH_CHAR_T char
#define PATH_TEXT(x) x
#endif

// 共有的
#define CONST               const
#define VOID                void
typedef char                CHAR;
typedef short               SHORT;
typedef long                LONG;
typedef int                 INT;
typedef unsigned int        UINT;
typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef CHAR*               PCHAR, * LPCH, * PCH;
typedef BYTE                BOOLEAN;
typedef CONST CHAR*         LPCCH, * PCCH;
typedef CONST CHAR*         LPCSTR, * PCSTR;
typedef wchar_t             WCHAR;    // wc,   16-bit UNICODE character
typedef WCHAR*              PWCHAR, * LPWCH, * PWCH;
typedef CONST WCHAR*        LPCWCH, * PCWCH;
typedef WCHAR*              NWPSTR, * LPWSTR, * PWSTR;
typedef void*               PVOID;
typedef unsigned long       ULONG;
typedef ULONG*              PULONG;
typedef unsigned short      USHORT;
typedef USHORT*             PUSHORT;
typedef unsigned char       UCHAR;
typedef UCHAR*              PUCHAR;
typedef void*               HANDLE;
typedef BYTE*               PBYTE;
typedef long                NTSTATUS, * PNTSTATUS;
typedef size_t              LONG_PTR;
typedef size_t              ULONG_PTR, * PULONG_PTR;
typedef ULONG_PTR           DWORD_PTR, * PDWORD_PTR;
typedef CONST WCHAR*        LPCWSTR, * PCWSTR;
typedef CHAR*               NPSTR, * LPSTR, * PSTR;
typedef BOOL *              LPBOOL;

// 基础数据类型定义
typedef bool                        B8;
typedef char                        C8;
typedef unsigned char               U8;
typedef signed short                I16;
typedef unsigned short              U16;
typedef int                         I32;
typedef unsigned int                U32;
typedef float                       F32;
typedef long long                   I64;
typedef unsigned long long          U64;
typedef double                      F64;

// ===================================================================== 数据类型重命名 ↑↑↑↑↑↑

// ===================================================================== 自定义宏 ↓↓↓↓↓↓
#ifndef NULL
#define NULL 0
#endif

#define MAX_PATH                                            260

#define FALSE               0
#define TRUE                1

// 编码相关
#define CP_ACP                    0           // default to ANSI code page
#define CP_OEMCP                  1           // default to OEM  code page
#define CP_MACCP                  2           // default to MAC  code page
#define CP_THREAD_ACP             3           // current thread's ANSI code page
#define CP_SYMBOL                 42          // SYMBOL translations
#define CP_UTF7                   65000       // UTF-7 translation
#define CP_UTF8                   65001       // UTF-8 translation

#define MB_PRECOMPOSED            0x00000001  // DEPRECATED: use single precomposed characters when possible.
#define MB_COMPOSITE              0x00000002  // DEPRECATED: use multiple discrete characters when possible.
#define MB_USEGLYPHCHARS          0x00000004  // DEPRECATED: use glyph chars, not ctrl chars
#define MB_ERR_INVALID_CHARS      0x00000008  // error for invalid chars

#define WC_COMPOSITECHECK         0x00000200  // convert composite to precomposed
#define WC_DISCARDNS              0x00000010  // discard non-spacing chars          // Used with WC_COMPOSITECHECK
#define WC_SEPCHARS               0x00000020  // generate separate chars            // Used with WC_COMPOSITECHECK
#define WC_DEFAULTCHAR            0x00000040  // replace w/ default char            // Used with WC_COMPOSITECHECK
#define WC_ERR_INVALID_CHARS      0x00000080  // error for invalid chars
#define WC_NO_BEST_FIT_CHARS      0x00000400  // do not use best fit chars

#define ERROR_INVALID_FLAGS              1004L
#define ERROR_INSUFFICIENT_BUFFER        122L    // dderror
#define ERROR_INVALID_PARAMETER          87L    // dderror
#define ERROR_NO_UNICODE_TRANSLATION     1113L

// 报文类型定义
#define PKG_TYPE_CONTRACT_IDX       0x05                // 合约索引
#define PKG_TYPE_CONTRACT_INIT      0x06                // 初始行情
#define PKG_TYPE_SGLCONT            0x10                // 单腿行情
#define PKG_TYPE_CMBCONT            0x11                // 组合行情
#define PKG_TYPE_PRODUCT_STATUS     0x12                // 品种交易状态
#define PKG_TYPE_QUOTE_REQ          0x13                // 报价请求
#define PKG_TYPE_MARKET_STATUS      0x14                // 市场交易状态
#define PKG_TYPE_SGLCONT_DEPTH      0x20                // 单腿深度行情
#define PKG_TYPE_CMBCONT_DEPTH      0x21                // 组合深度行情

// ===================================================================== 自定义宏 ↑↑↑↑↑↑

// ===================================================================== 业务无关的静态工具函数
// 停止文件是否存在
static inline bool isStopFileExist(const std::string& stop_file_path){
    std::filesystem::path stopAbsolutePath = std::filesystem::absolute(stop_file_path); // 相对路径转绝对路径
    if (access(stopAbsolutePath.c_str(), 0) == -1) {  // access=确定文件是否存在或者判断读写执行权限
        // 文件不存在，返回false
        return false;
    }
    else {
        return true;
    }
}

// 按空格分割字符串
static inline std::vector<std::string> splitBySpace(const std::string& str) {
    std::istringstream iss(str);
    std::vector<std::string> tokens;
    std::string token;

    while (iss >> token) {
        tokens.push_back(token);
    }

    return tokens;
}

// 按 特殊字符 分割字符串
static inline std::vector<std::string> splitByDelimiter(const std::string& str, char delimiter) {
    std::istringstream iss(str);
    std::vector<std::string> tokens;
    std::string token;

    while (std::getline(iss, token, delimiter)) {
        tokens.push_back(token);
    }

    return tokens;
}

// 删除 string 的左空格
static inline void ltrim(std::string &str) {
    str.erase(0, str.find_first_not_of(' '));
}

// 删除string 的右空格
static inline void rtrim(std::string &str) {
    size_t n = str.find_last_not_of('\0');
    size_t str_size = str.size();
    if (n != std::string::npos) {
        str.erase(n + 1, str_size - n);
    }

    n = str.find_last_not_of(' ');
    if (n != std::string::npos) {
        str.erase(n + 1, str_size - n);
    }
}

// 去除两边的空格
static inline void trim(std::string &str) {
    str.erase(0, str.find_first_not_of(' '));

    size_t n = str.find_last_not_of('\0');
    size_t str_size = str.size();
    if (n != std::string::npos) {
        str.erase(n + 1, str_size - n);
    }

    n = str.find_last_not_of(' ');
    if (n != std::string::npos) {
        str.erase(n + 1, str_size - n);
    }
}

// 获取当前时间
// 返回值样例：20241108 09:16:35
static inline std::string currTime() {
    char current_time[70];
    time_t tt = time(NULL);
    struct tm *t = localtime(&tt);
    sprintf(current_time, "%04d%02d%02d %02d:%02d:%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
    return current_time;
}

// str转int，n进制转十进制？
static inline int str_int(const std::string& str_in) {
    if (str_in == "" || str_in.length() == 0) {
        return 0;
    }
    return stoi(str_in);
}

// str转double，科学计数法的不能转
static inline double str_double(const std::string& str_in) {
    if (str_in == "" || str_in.length() == 0) {
        return 0;
    }
    if (str_in.find("E+") != std::string::npos || str_in.find("E-") != std::string::npos) {
        return 0;
    }
    return stod(str_in);
}

// double值和科学计数法之间进行转换，double值校验
static inline double sanitize_double(double value) {
    if (value > -1e100 && value < 1e100) return value;
    else return 0.0;
}

//
static inline uint16_t read_uint16(uint8_t* buf) {
    uint8_t* tbuf = (uint8_t*)buf;
    return (tbuf[0] << 8) + tbuf[1];
}

//
static inline uint32_t read_uint32(uint8_t* buf) {
    uint8_t* tbuf = (uint8_t*)buf;
    return (tbuf[0] << 24) + (tbuf[1] << 16) + (tbuf[2] << 8) + tbuf[3];
}

// 时间戳格式化
static inline std::string Stamp2Time(long long timestamp) {
    time_t tick = (time_t)(timestamp);//转换时间
    struct tm tm;
    char s[256];
    tm = *localtime(&tick);
    strftime(s, sizeof(s), "%H%M%S", &tm); //%Y-%m-%d  %Y%m%d
    return s;
}



#endif //NETWORK_TRAFFIC_PROCESSING_PCH_H
